#include "Game.h"

#include "EnemyData.h"
#include "EnemyDatabase.h"
#include "LevelManager.h"
#include "PlayerController.h"
#include "ItemDatabase.h"
#include "Cursor.h"
#include "ResourceDatabase.h"
#include "ResSound.h"
#include "ResImage.h"

Game::Game()
: active(false)
, paused(false)
{
}

Game::~Game()
{
    // Clean up singletons, etc.
}

bool Game::isActive() const
{
    return active;
}

void Game::setActive(bool active)
{
    this->active = active;
}

bool Game::isPaused() const
{
	return paused;
}

void Game::setPaused(bool paused)
{
    this->paused = paused;
}

void Game::reset()
{
    // clean up any singletons etc.
    LevelManager::cleanUp();
    EnemyManager::cleanUp();

    active = false;
    paused = false;

    setName("");
}

void Game::newGame(const std::string& defaultGameName, const std::string& gameName)
{
    //Reset();

    ///// First, save a copy of the default game folder as the new game.

    //// The folder where the source game is stored.
    //const boost_path srcGameDir(STGS.savesDir() / defaultGameName);
    //// The folder where the destination game is to be stored.
    //const boost_path dstGameDir(STGS.Saves_Dir() / gameName);

    //copy_dir(srcGameDir, dstGameDir);

    ///// Then load the newly saved copy.

    //loadGame(gameName);

    // ==================================================
    // Temporary code!
    // ==================================================

    //======================================================
    //      RESOURCE DATABASE HAS FULLY IMPLEMENTATED XML I/O, THIS IS BACKUP CODE:
    //     ResourceDatabase::get().addSound(0, "data/audio/sounds/Roland.wav", SOUND_REPEAT | SOUND_GLOBAL, sf::Vector2i(0, 0), 100.0f, 1.0f);
    //     ResourceDatabase::get().addImage(IMG_BULLET, 0, 0, "data/sprites/bullet.png");
    //     ResourceDatabase::get().addImage(IMG_CURSOR_DEFAULT, 0, 0, "data/sprites/cursors/default.png");
    //     ResourceDatabase::get().addImage(IMG_HAND, 0, 0, "data/sprites/HandWithGun.png");
    //     ResourceDatabase::get().addImage(IMG_INVENTORY, 0, 0, "data/sprites/Inventory.png");
    //     ResourceDatabase::get().addImage(IMG_SANTA, 1, 13, "data/sprites/chanta_running.png");
    //     ResourceDatabase::get().addImage(IMG_TREE, 0, 0, "data/sprites/littletree003.png");
    //     ResourceDatabase::get().addImage(IMG_TEST_ITEM, 0, 0, "data/sprites/ItemIcon.png");
    //======================================================
    //      RESOURCE DATABASE HAS FULLY IMPLEMENTATED XML I/O, THIS IS BACKUP CODE:
    //EnemyDatabase::get().addEnemyData(EnemyData(IMG_TREE, 100), 0);
    //======================================================
    //      IMAGE DATABASE HAS FULLY IMPLEMENTATED XML I/O, THIS IS BACKUP CODE:
    //ItemDatabase::initialise("");
    //ItemDatabase::get().addItemData(ItemData(AnimatedSpritePtr(new AnimatedSprite(IMG_TEST_ITEM)),0.5, 500, 10), 0);
    //======================================================
    //TESTED, NO MORE REQUIRED
    //animTest = AnimatedSprite(IMG_SANTA);
    //animTest.addAnimation(Animation(4, 0, 0, 13, 1.0f));
    //animTest.playAnimation(ANIM_RUN_RIGHT);
    //======================================================


    myInv = InventoryPtr(new Inventory(IMG_INVENTORY));

    EnemyManager::initialise("");
    
    // Or alternatively, myPers = EntityPtr(new Entity(...));
    player.reset(new Player(sf::Vector2f(0,0), 1,
        AnimatedSpritePtr(new AnimatedSprite(IMG_TREE))));
    camera = CameraPtr(new Camera(sf::IntRect((sf::Vector2i)player->getPosition(),(sf::Vector2i)player->getSprite()->GetSize())));
    window->SetView(camera->getView());
    LevelManager::initialise("", player);

    myPers3.reset(new Enemy(sf::Vector2f(200,400), 0));
    myPers2.reset(new Enemy(sf::Vector2f(400,200), 0));    
	
    LevelPtr currentLevel = LevelManager::get().getCurrentLevel();
	currentLevel->addEnemy(myPers2);
	currentLevel->addEnemy(myPers3);


    playerController = PlayerController(player, camera, "");

    MyFont.LoadFromFile("data/gui/fonts/arial.ttf");
    //text = sf::Text("Paused", MyFont, 20);
    text.SetColor(sf::Color::Blue);

    myInv->addItem(ItemPtr(new Item(0)), 30);

}

void Game::loadGame(const std::string& gameName)
{
    reset();

    // The folder where the game is stored.
    //const boost_path gameDir(STGS.Saves_Dir() / gameName);

    //npcDatabase::initialise(gameDir / STGS.npcDir() / "npc_database.xml");
  
    //switchDatabase::initialise(gameDir / "switch_database.xml");

    /// Load GUI stuff.

    /// Load the starting level, etc.
     
    setActive(true);
    setPaused(false);
    setName(name);
}

void Game::saveGame(const std::string& gameName)
{
    // The folder where the game is stored.
    //const boost_path gameDir(STGS.Saves_Dir() / gameName);
    
    //NPC_Database::Get().writeFile(gameDir / STGS.npcDir() / "npc_database.xml");
  
    //Switch_Database::Get().writeFile(gameDir / "switch_database.xml");
}

void Game::deleteActiveGame()
{
    if(!isActive())
    {
        return;
    }

    deleteGame(getName(), true);

    reset();
}

bool Game::deleteGame(const std::string& gameName, bool throwOnFail)
{
    //// The folder where the game is stored.
    //const boost_path gameDir(STGS.Saves_Dir() / gameName);

    //bool pathExists = boost::filesystem::exists(gameDir);
    //if(!pathExists || pathExists && !is_directory(gameDir))
    //{
    //    if(throwOnFail)
    //    {
    //        throw LRE_Exception("Saved game \"" + gameName + "\" doesn't exist.");
    //    }
    //    else
    //    {
    //        return false;
    //    }
    //}

    //unsigned long qtyRemoved = boost::filesystem::remove_all(gameDir);
    //if(qtyRemoved == 0)
    //{
    //    if(throwOnFail)
    //    {
    //        throw LRE_Exception("Couldn't remove saved game \"" + gameName + "\".");
    //    }
    //    else
    //    {
    //        return false;
    //    }
    //}

    return true;
}

void Game::setWindow(sf::RenderWindow* window)
{
    this->window = window;
}

void Game::update(sf::RenderWindow& window, sf::Event& event)
{
    if(isActive())
    {
        if(isPaused())
        { // Game is paused.
            if((event.Type == sf::Event::KeyReleased) && (event.Key.Code == sf::Key::Back))
            {
                setPaused(false);
            }
        }
        else
        { // Not paused.            
            if((event.Type == sf::Event::KeyReleased) && (event.Key.Code == sf::Key::Back))
            {
                setPaused(true);
            }

            //Passing window input to PlayerController
            if (!paused)
            {
                playerController.update(window);
            }

        }
        if((event.Type == sf::Event::KeyReleased) && (event.Key.Code == sf::Key::I))//inventory
        {
            myInv->swapShow();
            swapPaused();
        }
        if((event.Type == sf::Event::KeyReleased) && (event.Key.Code == sf::Key::M))//Music
        {
            bool psd = ResourceDatabase::get().getSound(0)->Paused;
            (ResourceDatabase::get().getSound(0)->GetStatus() != sf::SoundSource::Playing)
                ? ResourceDatabase::get().getSound(0)->smoothPlay(5)
                : ResourceDatabase::get().getSound(0)->smoothPause(5);
        }
        if((event.Type == sf::Event::KeyReleased) && (event.Key.Code == sf::Key::F))//inventory
        {
            EnemyDatabase::get().save("TestSave");
        }
        if (myInv->getShow())
        {
            myInv->update(window);
        }
        if (myInv->getShow() &&
            window.GetInput().GetMouseX() > myInv->getBgSprite().GetPosition().x &&
            window.GetInput().GetMouseX() < myInv->getBgSprite().GetPosition().x + myInv->getBgSprite().GetImage()->GetWidth() &&
            window.GetInput().GetMouseY() > myInv->getBgSprite().GetPosition().y &&
            window.GetInput().GetMouseY() < myInv->getBgSprite().GetPosition().y + myInv->getBgSprite().GetImage()->GetHeight())
        {
            //hand cursor
        }
    }
}

void Game::update(float delta)
{
    if(isActive() && !isPaused())
    {
        //animTest.update(delta);
        playerController.update(delta);
        EnemyManager::get().update(delta);
        LevelManager::get().update(delta);
    }
    ResourceDatabase::get().update(delta);
}

void Game::render(sf::RenderWindow& window)
{
    if(isActive())
    {
        window.Clear();
        //window.Draw(animTest);
        window.Draw(text);
        playerController.draw(window);        
        EnemyManager::get().draw(window);
        LevelManager::get().render(window);
        myInv->render(window);
        Cursor::get()->update();
        window.SetView(camera->getView());
        window.Display();
    }
}

void Game::swapPaused()
{
    paused = (paused) ? false : true;
}
